package com.skyyan.netty.jjf.util;

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.ByteUtil;

/**
 * 设备序列号 (24位) 与 字节数组 互转工具类 (采用低位在前/小端序)
 *
 * 示例: 序列号 0x123456
 *       字节数组 (小端序): [0x56, 0x34, 0x12]
 */
public class SerialNOConverterUtil {

    /**
     * 将设备序列号（24位整数）转换为3字节的低位在前（Little-Endian）字节数组。
     * @param serialNO 设备序列号，范围 0x000000 - 0xFFFFFF。
     * @return 3字节的字节数组，索引0为最低有效字节(LSB)。
     * @throws IllegalArgumentException 如果序列号超出24位范围。
     */
    public static byte[] serialNOToBytes(int serialNO) {
        if (serialNO < 0 || serialNO > 0xFFFFFF) {
            throw new IllegalArgumentException("设备序列号必须在 0x000000 到 0xFFFFFF 范围内");
        }
        byte[] bytes = new byte[3];
        bytes[0] = (byte) (serialNO & 0xFF);          // LSB (最低有效字节)
        bytes[1] = (byte) ((serialNO >> 8) & 0xFF);   // 中间字节
        bytes[2] = (byte) ((serialNO >> 16) & 0xFF);  // MSB (最高有效字节)
        return bytes;
    }

    /**
     * 将3字节的低位在前字节数组转换回设备序列号。
     * @param bytes 3字节的字节数组，索引0为最低有效字节(LSB)。
     * @return 设备序列号。
     * @throws IllegalArgumentException 如果数组为null或长度不等于3。
     */
    public static int bytesToSerialNO(byte[] bytes) {
        if (bytes == null || bytes.length != 3) {
            throw new IllegalArgumentException("字节数组必须是3字节长");
        }
        // 注意: Java byte 是有符号的，使用 & 0xFF 转为无符号 int
        return (bytes[2] & 0xFF) << 16 | (bytes[1] & 0xFF) << 8 | (bytes[0] & 0xFF);
    }

    /**
     * (可选) 从表示24位序列号的十六进制字符串创建小端序字节数组。
     * 字符串长度应为6（如 "123456" 或 "0x123456"）。
     * @param hexString 表示序列号的十六进制字符串。
     * @return 3字节的小端序字节数组。
     */
    public static byte[] hexStringToSerialNOBytes(String hexString) {
        // 移除可能的 "0x" 前缀
        String cleanHex = hexString.startsWith("0x") || hexString.startsWith("0X") ?
                hexString.substring(2) : hexString;

        if (cleanHex.length() != 6) {
            throw new IllegalArgumentException("十六进制字符串必须是6个字符长");
        }

        // Hutool HexUtil.decodeHex 返回大端序 (高位在前)
        byte[] bigEndianBytes = HexUtil.decodeHex(cleanHex);
        // 转换为小端序 (低位在前): 反转字节顺序
        return new byte[]{bigEndianBytes[2], bigEndianBytes[1], bigEndianBytes[0]};
    }

    /**
     * (可选) 将小端序的3字节序列号数组格式化为十六进制字符串（大端序表示）。
     * @param serialNOBytes 3字节的小端序序列号数组。
     * @return 格式化后的十六进制字符串 (如 "123456")。
     */
    public static String serialNOBytesToHexString(byte[] serialNOBytes) {
        if (serialNOBytes == null || serialNOBytes.length != 3) {
            throw new IllegalArgumentException("字节数组必须是3字节长");
        }
        // 先转换为大端序以便正确显示
        byte[] bigEndian = new byte[]{serialNOBytes[2], serialNOBytes[1], serialNOBytes[0]};
        return HexUtil.encodeHexStr(bigEndian).toUpperCase();
    }

    // --- 测试方法 ---
    public static void main(String[] args) {
        // 测试用例1: 使用整数
        int serialNO = 0x123456;
        System.out.println("=== 测试用例 1: 整数转换 ===");
        byte[] bytes1 = serialNOToBytes(serialNO);
        System.out.printf("序列号 (int): 0x%06X%n", serialNO);
        System.out.printf("字节数组 (小端序): [%s]%n", HexUtil.encodeHexStr(bytes1));
        int restoredNO1 = bytesToSerialNO(bytes1);
        System.out.printf("恢复的序列号: 0x%06X%n", restoredNO1);

        // 测试用例2: 使用十六进制字符串
        String hexStr = "123456";
        System.out.println("\n=== 测试用例 2: 十六进制字符串转换 ===");
        byte[] bytes2 = hexStringToSerialNOBytes(hexStr);
        System.out.printf("序列号 (hex): %s%n", hexStr);
        System.out.printf("字节数组 (小端序): [%s]%n", HexUtil.encodeHexStr(bytes2));
        String restoredHex = serialNOBytesToHexString(bytes2);
        System.out.printf("恢复的十六进制: %s%n", restoredHex);

        // 演示如何放入更大的数组
        System.out.println("\n=== 放入更大数组示例 ===");
        byte[] fullArray = new byte[9]; // 假设总长度为9
        System.arraycopy(bytes1, 0, fullArray, 6, 3); // 复制到索引 6, 7, 8
        for (int i = 6; i < 9; i++) {
            System.out.printf("fullArray[%d] = 0x%02X%n", i, fullArray[i] & 0xFF);
        }
    }
}
